#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/udp.h>

#define DHCP_SERVER_PORT 67
#define DHCP_CLIENT_PORT 68
#define IP_ADDRESS "192.168.1.2"
#define SUBNET_MASK "255.255.255.0"
#define DEFAULT_GATEWAY "192.168.1.1"
#define DNS_SERVER "8.8.8.8"

// 构建DHCP响应报文
void build_dhcp_reply(char *reply, struct sockaddr_in *client_addr) {
    // 简单构建DHCP发现阶段的响应报文
    // 实际应用中需要处理更多字段和状态
    memset(reply, 0, 576);
    reply[0] = 2; // 消息类型：BOOTREPLY
    reply[1] = 1; // 硬件类型：以太网
    reply[2] = 6; // 硬件地址长度
    reply[3] = 0; // 跳数
    // 事务ID，可随机生成
    reply[4] = rand() & 0xFF;
    reply[5] = rand() & 0xFF;
    reply[6] = rand() & 0xFF;
    reply[7] = rand() & 0xFF;
    reply[8] = 0; // 秒数
    reply[9] = 0; // 标志位
    // 客户端IP地址
    inet_pton(AF_INET, "0.0.0.0", &reply[12]);
    // 你的IP地址
    inet_pton(AF_INET, IP_ADDRESS, &reply[16]);
    // 服务器IP地址
    inet_pton(AF_INET, IP_ADDRESS, &reply[20]);
    // 网关IP地址
    inet_pton(AF_INET, DEFAULT_GATEWAY, &reply[24]);
    // 客户端硬件地址
    memcpy(&reply[28], &client_addr->sin_addr, sizeof(client_addr->sin_addr));
    // 填充选项字段
    reply[236] = 53; // 选项：DHCP消息类型
    reply[237] = 2; // DHCP Offer
    reply[238] = 1; // 长度
    reply[239] = 2;
    reply[240] = 51; // 选项：IP地址租期
    reply[241] = 4; // 长度
    reply[242] = 0;
    reply[243] = 0;
    reply[244] = 0;
    reply[245] = 60; // 租期60秒，可调整
    reply[246] = 1; // 子网掩码选项
    reply[247] = 4; // 长度
    inet_pton(AF_INET, SUBNET_MASK, &reply[248]);
    reply[252] = 3; // 路由器选项
    reply[253] = 4; // 长度
    inet_pton(AF_INET, DEFAULT_GATEWAY, &reply[254]);
    reply[258] = 6; // DNS服务器选项
    reply[259] = 4; // 长度
    inet_pton(AF_INET, DNS_SERVER, &reply[260]);
    reply[264] = 255; // 选项结束
}

int main() {
    int sockfd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);
    char buffer[576];

    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sockfd < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&server_addr, 0, sizeof(server_addr));
    memset(&client_addr, 0, sizeof(client_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(DHCP_SERVER_PORT);

    if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    while (1) {
        ssize_t n = recvfrom(sockfd, (char *)buffer, sizeof(buffer), MSG_WAITALL,
                             (struct sockaddr *) &client_addr, &client_len);
        if (n < 0) {
            perror("recvfrom failed");
            break;
        }
        // 检查是否为DHCP Discover报文
        if (buffer[0] == 1 && buffer[236] == 53 && buffer[237] == 1) {
            char reply[576];
            build_dhcp_reply(reply, &client_addr);
            if (sendto(sockfd, (const char *)reply, sizeof(reply), MSG_CONFIRM,
                       (const struct sockaddr *) &client_addr, client_len) < 0) {
                perror("sendto failed");
            }
        }
    }

    close(sockfd);
    return 0;
}